using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using ParadoxNotion;
using UnityEditor;
using UnityEngine;

namespace Nirvana.AB
{
    public class AssetBundleBuilder
    {
        /// <summary>
        /// 导出AssetBundle
        /// </summary>
        /// <param name="outputPath">导出地址</param>
        /// <returns></returns>
        public string Export()
        {
            Analyze();
            var abPackers = new List<ABPacker>();
            var assetPaths = new HashSet<string>();
            var manifestBundleName = BundleUtils.GetPlatformName().ToLower();
            var outputPath = Path.Combine("assetbundles", manifestBundleName);
            BuildAB(assetPaths, abPackers, manifestBundleName, outputPath);
            assetPaths.Clear();
            abPackers.Clear();
            
            return "";
        }

        private void BuildAB(HashSet<string> assetPaths, List<ABPacker> abPackers, string manifestBundleName, string outputPath)
        {
            outputPath = Path.Combine(outputPath, "resources");
            
            if (!Directory.Exists(outputPath))
            {
                Directory.CreateDirectory(outputPath);
            }
            
            var allAssets = AssetBundleUtils.GetCombineAsset();
            var abBuilds = new List<AssetBundleBuild>();
            assetPaths.Add(manifestBundleName);
            BeforeBuild(abBuilds, abPackers);
            foreach (var target in allAssets)
            {
                var assetBundleName = AssetBundleUtils.ToABName(target.assetPath.Replace('\\', '/'));
                if (!assetPaths.Contains(assetBundleName))
                {
                    assetPaths.Add(assetBundleName);
                    var build = new AssetBundleBuild {assetBundleName = assetBundleName, assetNames = new[] {target.assetPath}};
                    abBuilds.Add(build);
                }
            }
            
            AssetDatabase.Refresh();
            EditorUtility.DisplayProgressBar("BuildPipeline", "BuildAssetBundles...", 0f);
            var manifest = BuildPipeline.BuildAssetBundles(outputPath, abBuilds.ToArray(), BuildAssetBundleOptions.ChunkBasedCompression, EditorUserBuildSettings.activeBuildTarget);
            EditorUtility.ClearProgressBar();
            if (manifest == null)
            {
                Debug.LogError("打包失败!!!");
                return;
            }
            
            
        }

        /// <summary>
        /// 将ABPacker中的资源内容都生成Build
        /// </summary>
        /// <param name="builds"></param>
        /// <param name="packers"></param>
        private void BeforeBuild(List<AssetBundleBuild> builds, List<ABPacker> packers)
        {
            foreach (var packer in packers)
            {
                if (packer.isABPacker)
                {
                    foreach (var pair in packer.abPaths)
                    {
                        var build = new AssetBundleBuild();
                        build.assetBundleName = pair.Key;
                        build.assetNames = pair.Value.ToArray();
                        builds.Add(build);
                    }
                }
            }
        }

        /// <summary>
        /// 解析依赖，此时GetAllAssets获取的资源列表还是我们主动添加的需要打包的资源。等解析过后，就会包含所有处理过依赖的资源。除了Shader文件
        /// </summary>
        private void Analyze()
        {
            List<AssetTarget> all = AssetBundleUtils.GetAllAssets();
            int count = Math.Max(all.Count, 1);
            EditorUtility.DisplayProgressBar("Bundle Analyze", $"Analyze...{0}/{count}", 0f);
            for (int i = 0; i < all.Count; i++)
            {
                all[i].Analyze();
                EditorUtility.DisplayProgressBar("Bundle Analyze", $"Analyze...{i}/{count}", i / (float) count);
            }

            EditorUtility.ClearProgressBar();
        }
    }
}